#ifndef _MODEL_H
#define _MODEL_H

#include <map>
namespace math { namespace ui {
class GLView ;
class Model
{
public :


	typedef float value_type; 
	typedef math::hierarchy_mesh_traits<value_type, 3> mesh_traits_type; 
	typedef math::HierarchyMesh<mesh_traits_type >  mesh_type ;
	typedef math::hierarchy_mesh_traits <value_type, 3>::FaceType            face_type ;
	typedef math::AABBTreePoly <value_type, 3>                        tree_type ;
	typedef math::PseudoMesh<value_type , 3 >                         pseudomesh_type ;

	typedef math::Sphere<value_type, 3>              sphere_type ;
	typedef math::Polygon<value_type, 3>             polygon_type ;
	typedef math::vector<value_type, 3>              point3f ;
	typedef math::vector<value_type, 2>              point2f ;
	typedef math::vector<value_type, 3>              vector3f ;
	typedef math::vector<value_type, 2>              vector2f ;


	Model () : mp_mesh (NULL), mp_texture(NULL), mp_pseudo_mesh(NULL), mp_brush (NULL)
	{
		//mp_brush = new SolidBrush ;
		mp_brush = new GaussianBrush ;
	}

	void get_solid_grush () 
	{
		if (mp_brush)
			delete (mp_brush );
		mp_brush = new SolidBrush ;
	}

	void get_gaussian_grush () 
	{
		if (mp_brush)
			delete (mp_brush );
		mp_brush = new GaussianBrush ;
	}

	virtual ~ Model () 
	{
		if (mp_mesh) delete mp_mesh; 
		if (mp_texture ) delete mp_texture ;
		if (mp_pseudo_mesh ) delete mp_pseudo_mesh ;
		if (mp_brush) delete mp_brush ;
	}

	mesh_type * load_mesh (const char * filename)
	{
		mp_texture = new Texture (texture_height, texture_width); 
		
		std::ifstream ifs (filename);
		mp_mesh = new mesh_type; 

		//ifs >> (*mp_mesh) ;
		mp_mesh->OBJ_reader (ifs);
		mp_mesh->build_hierarchy();

		mp_pseudo_mesh = new pseudomesh_type (mp_mesh);
	}
	mesh_type * get_mesh () {return this->mp_mesh; }
	pseudomesh_type * get_pseudomesh () {return this->mp_pseudo_mesh ;}
	Texture * get_texture () { return this->mp_texture; }
	tree_type * get_tree () {return this->mp_tree;  }
	Brush * get_brush () {return this->mp_brush ; }
	
	void add_control(GLView * pview, unsigned ID) 
	{
		m_controls.insert (std::make_pair (ID, pview));
	}
	GLView * query_control (unsigned ID)
	{
		return this->m_controls[ID] ;
	}

	void set_layer (unsigned id){ m_layer_id = id ; mp_brush->m_layer_id = id ;}
	unsigned get_layer_id () const { return this->m_layer_id ;}

private :
	mesh_type * mp_mesh; 
	pseudomesh_type * mp_pseudo_mesh; 
	
	Texture * mp_texture; 
	tree_type * mp_tree; 
	static const unsigned texture_height = 4096; 
	static const unsigned texture_width = 2248; 
	
	Brush * mp_brush ;

	std::map<unsigned , GLView * > m_controls; 
	unsigned m_layer_id ;

};

	}}
#endif

